/*
 * Copyright (C) 2008 Universidade Federal de Campina Grande
 *  
 * This file is part of OurGrid. 
 *
 * OurGrid is free software: you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License as published by the Free 
 * Software Foundation, either version 3 of the License, or (at your option) 
 * any later version. 
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT 
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
 * for more details. 
 * 
 * You should have received a copy of the GNU Lesser General Public License 
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 * 
 */
package org.ourgrid.acceptance.peer;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ScheduledFuture;

import org.easymock.classextension.EasyMock;
import org.junit.After;
import org.junit.Test;
import org.ourgrid.acceptance.util.PeerAcceptanceUtil;
import org.ourgrid.acceptance.util.RemoteAllocation;
import org.ourgrid.acceptance.util.WorkerAcceptanceUtil;
import org.ourgrid.acceptance.util.WorkerAllocation;
import org.ourgrid.acceptance.util.peer.Req_010_Util;
import org.ourgrid.acceptance.util.peer.Req_011_Util;
import org.ourgrid.acceptance.util.peer.Req_014_Util;
import org.ourgrid.acceptance.util.peer.Req_016_Util;
import org.ourgrid.acceptance.util.peer.Req_018_Util;
import org.ourgrid.acceptance.util.peer.Req_019_Util;
import org.ourgrid.acceptance.util.peer.Req_020_Util;
import org.ourgrid.acceptance.util.peer.Req_025_Util;
import org.ourgrid.acceptance.util.peer.Req_027_Util;
import org.ourgrid.acceptance.util.peer.Req_101_Util;
import org.ourgrid.acceptance.util.peer.Req_108_Util;
import org.ourgrid.acceptance.util.peer.Req_115_Util;
import org.ourgrid.common.interfaces.LocalWorkerProviderClient;
import org.ourgrid.common.interfaces.RemoteWorkerProvider;
import org.ourgrid.common.interfaces.control.PeerControl;
import org.ourgrid.common.interfaces.control.PeerControlClient;
import org.ourgrid.common.interfaces.to.GridProcessAccounting;
import org.ourgrid.common.interfaces.to.GridProcessState;
import org.ourgrid.common.interfaces.to.RequestSpec;
import org.ourgrid.common.spec.job.JobSpec;
import org.ourgrid.common.spec.worker.WorkerSpec;
import org.ourgrid.deployer.xmpp.XMPPAccount;
import org.ourgrid.discoveryservice.DiscoveryServiceConstants;
import org.ourgrid.peer.PeerComponent;
import org.ourgrid.peer.PeerConfiguration;
import org.ourgrid.peer.PeerConstants;
import org.ourgrid.reqtrace.ReqTest;

import br.edu.ufcg.lsd.commune.CommuneRuntimeException;
import br.edu.ufcg.lsd.commune.container.ObjectDeployment;
import br.edu.ufcg.lsd.commune.functionaltests.util.TestStub;
import br.edu.ufcg.lsd.commune.identification.ContainerID;
import br.edu.ufcg.lsd.commune.identification.DeploymentID;
import br.edu.ufcg.lsd.commune.test.AcceptanceTestUtil;

public class AT_0033 extends PeerAcceptanceTestCase {

	private static final String AUX_FILES_PATH = "it_0033" + File.separator;
	private static final String RANKING_FILEPATH = PeerAcceptanceUtil.TEST_FILES_PATH + AUX_FILES_PATH + "file.dat"; 
	
	private PeerComponent peerComponent;
	private WorkerAcceptanceUtil workerAcceptanceUtil = new WorkerAcceptanceUtil(getComponentContext());
    private Req_010_Util req_010_Util = new Req_010_Util(getComponentContext());
    private Req_011_Util req_011_Util = new Req_011_Util(getComponentContext());
    private Req_014_Util req_014_Util = new Req_014_Util(getComponentContext());
    private Req_016_Util req_016_Util = new Req_016_Util(getComponentContext());
    private Req_018_Util req_018_Util = new Req_018_Util(getComponentContext());
    private Req_019_Util req_019_Util = new Req_019_Util(getComponentContext());
    private Req_020_Util req_020_Util = new Req_020_Util(getComponentContext());
    private Req_025_Util req_025_Util = new Req_025_Util(getComponentContext());
    private Req_027_Util req_027_Util = new Req_027_Util(getComponentContext());
    private Req_101_Util req_101_Util = new Req_101_Util(getComponentContext());
    private Req_108_Util req_108_Util = new Req_108_Util(getComponentContext());
    private Req_115_Util req_115_Util = new Req_115_Util(getComponentContext());

    @After
	public void tearDown() throws Exception {
		super.tearDown();
		peerAcceptanceUtil.deleteFile(RANKING_FILEPATH);
	}
	
	@ReqTest(test="AT-0033", reqs="REQ011, REQ016, REQ027, REQ110, REQ111, REQ115")
	@Test public void test_AT_0033_LocalAndRemoteRedistributionWithSubcommunitiesConsideringMatchAndUnwantedWorkersAndNofPersistence()
			throws Exception {
	
		//Create two user accounts
		XMPPAccount user1 = req_101_Util.createLocalUser("user01", "server01", "011011");
		XMPPAccount user2 = req_101_Util.createLocalUser("user02", "server01", "011011");
		
		//Start the peer with the property peer.rankingfile set to a file that does not exist
		getComponentContext().set(PeerConfiguration.PROP_RANKINGFILE, RANKING_FILEPATH);
		//peerComponent = peerAcceptanceUtil.createPeerComponent(getComponentContext());
		
		//Expect the peer to schedule the file save of the network of favors data
		/*req_115_Util.startPeerVerifyingAccountingSavingWithReadingError(peerComponent,
				"The ranking file [" + RANKING_FILEPATH + "] could not be loaded. Using empty NoF data.");*/
		peerComponent = req_010_Util.startPeer();
		
		//Set workers
		req_010_Util.setWorkers(peerComponent, AUX_FILES_PATH + "TI_0033.sdf", getComponentContext());
		
		//Notify workers recovery
		String workerServerName = "xmpp.ourgrid.org";

		WorkerSpec workerSpecA = workerAcceptanceUtil.createWorkerSpec("workera", workerServerName);
		workerSpecA.putAttribute(WorkerSpec.ATT_MEM, "4");
		workerSpecA.putAttribute(WorkerSpec.ATT_PROVIDER_PEER, getPeerAddress());
		
		String workerAPublicKey = "workerAPublicKey";
		DeploymentID workerAID = req_019_Util.notifyWorkerRecovery(peerComponent, workerSpecA, workerAPublicKey);
		
		WorkerSpec workerSpecB = workerAcceptanceUtil.createWorkerSpec("workerb", workerServerName);
		workerSpecB.putAttribute(WorkerSpec.ATT_MEM, "8");
		String workerBPublicKey = "workerBPublicKey";
		DeploymentID workerBID = req_019_Util.notifyWorkerRecovery(peerComponent, workerSpecB, workerBPublicKey);

		WorkerSpec workerSpecC = workerAcceptanceUtil.createWorkerSpec("workerc", workerServerName);
		workerSpecC.putAttribute(WorkerSpec.ATT_MEM, "16");
		String workerCPublicKey = "workerCPublicKey";
		DeploymentID workerCID = req_019_Util.notifyWorkerRecovery(peerComponent, workerSpecC, workerCPublicKey);

		WorkerSpec workerSpecD = workerAcceptanceUtil.createWorkerSpec("workerd", workerServerName);
		workerSpecD.putAttribute(WorkerSpec.ATT_MEM, "32");
		String workerDPublicKey = "workerDPublicKey";
		DeploymentID workerDID = req_019_Util.notifyWorkerRecovery(peerComponent, workerSpecD, workerDPublicKey);

		WorkerSpec workerSpecE = workerAcceptanceUtil.createWorkerSpec("workere", workerServerName);
		workerSpecE.putAttribute(WorkerSpec.ATT_MEM, "64");
		String workerEPublicKey = "workerEPublicKey";
		DeploymentID workerEID = req_019_Util.notifyWorkerRecovery(peerComponent, workerSpecE, workerEPublicKey);
		
		WorkerSpec workerSpecF = workerAcceptanceUtil.createWorkerSpec("workerf", workerServerName);
		workerSpecF.putAttribute(WorkerSpec.ATT_MEM, "128");
		String workerFPublicKey = "workerFPublicKey";
		DeploymentID workerFID = req_019_Util.notifyWorkerRecovery(peerComponent, workerSpecF, workerFPublicKey);
		
		WorkerSpec workerSpecG = workerAcceptanceUtil.createWorkerSpec("workerg", workerServerName);
		workerSpecG.putAttribute(WorkerSpec.ATT_MEM, "256");
		String workerGPublicKey = "workerGPublicKey";
		DeploymentID workerGID = req_019_Util.notifyWorkerRecovery(peerComponent, workerSpecG, workerGPublicKey);

		WorkerSpec workerSpecH = workerAcceptanceUtil.createWorkerSpec("workerh", workerServerName);
		workerSpecH.putAttribute(WorkerSpec.ATT_MEM, "512");
		String workerHPublicKey = "workerHPublicKey";
		DeploymentID workerHID = req_019_Util.notifyWorkerRecovery(peerComponent, workerSpecH, workerHPublicKey);

		WorkerSpec workerSpecI = workerAcceptanceUtil.createWorkerSpec("workeri", workerServerName);
		workerSpecI.putAttribute(WorkerSpec.ATT_MEM, "1024");
		String workerIPublicKey = "workerIPublicKey";
		DeploymentID workerIID = req_019_Util.notifyWorkerRecovery(peerComponent, workerSpecI, workerIPublicKey);
		
		WorkerSpec workerSpecJ = workerAcceptanceUtil.createWorkerSpec("workerj", workerServerName);
		workerSpecJ.putAttribute(WorkerSpec.ATT_MEM, "2048");
		String workerJPublicKey = "workerJPublicKey";
		DeploymentID workerJID = req_019_Util.notifyWorkerRecovery(peerComponent, workerSpecJ, workerJPublicKey);
		
		WorkerSpec workerSpecK = workerAcceptanceUtil.createWorkerSpec("workerk", workerServerName);
		workerSpecK.putAttribute(WorkerSpec.ATT_MEM, "4096");
		String workerKPublicKey = "workerKPublicKey";
		DeploymentID workerKID = req_019_Util.notifyWorkerRecovery(peerComponent, workerSpecK, workerKPublicKey);
		
		WorkerSpec workerSpecL = workerAcceptanceUtil.createWorkerSpec("workerl", workerServerName);
		workerSpecL.putAttribute(WorkerSpec.ATT_MEM, "8192");
		String workerLPublicKey = "workerLPublicKey";
		DeploymentID workerLID = req_019_Util.notifyWorkerRecovery(peerComponent, workerSpecL, workerLPublicKey);
		
		//Change workers status to IDLE
		req_025_Util.changeWorkerStatusToIdle(peerComponent, workerLID);
		req_025_Util.changeWorkerStatusToIdle(peerComponent, workerKID);
		req_025_Util.changeWorkerStatusToIdle(peerComponent, workerJID);
		req_025_Util.changeWorkerStatusToIdle(peerComponent, workerIID);
		req_025_Util.changeWorkerStatusToIdle(peerComponent, workerHID);
		req_025_Util.changeWorkerStatusToIdle(peerComponent, workerGID);
		req_025_Util.changeWorkerStatusToIdle(peerComponent, workerFID);
		req_025_Util.changeWorkerStatusToIdle(peerComponent, workerEID);
		req_025_Util.changeWorkerStatusToIdle(peerComponent, workerDID);
		req_025_Util.changeWorkerStatusToIdle(peerComponent, workerCID);
		req_025_Util.changeWorkerStatusToIdle(peerComponent, workerBID);
		req_025_Util.changeWorkerStatusToIdle(peerComponent, workerAID);
		
		//NodeWiz recovery
		DeploymentID dsID = new DeploymentID(new ContainerID("magoDosNos", "sweetleaf.lab", DiscoveryServiceConstants.MODULE_NAME),
				DiscoveryServiceConstants.DS_OBJECT_NAME);
		
		req_020_Util.notifyDiscoveryServiceRecovery(peerComponent, dsID);
		
		//Login with two valid users
		String myGrid1PubKey = "myGrid1PubKey"; 
		
		PeerControl peerControl = peerAcceptanceUtil.getPeerControl();
		ObjectDeployment pcOD = peerAcceptanceUtil.getPeerControlDeployment();
		
		PeerControlClient peerControlClient = EasyMock.createMock(PeerControlClient.class);
		
		DeploymentID pccID = new DeploymentID(new ContainerID("pcc", "broker", "broker"), myGrid1PubKey);
		AcceptanceTestUtil.publishTestObject(peerComponent, pccID, peerControlClient, PeerControlClient.class);
		
		AcceptanceTestUtil.setExecutionContext(peerComponent, pcOD, pccID);
		
		try {
			peerControl.addUser(peerControlClient, user1.getUsername() + "@" + user1.getServerAddress(), user1.getUserpassword());
		} catch (CommuneRuntimeException e) {
			//do nothing - the user is already added.
		}
		
		DeploymentID lwpc1OID = req_108_Util.login(peerComponent, user1, myGrid1PubKey);
		
		LocalWorkerProviderClient lwpc1 = (LocalWorkerProviderClient) AcceptanceTestUtil.getBoundObject(lwpc1OID);
		
		String myGrid2PubKey = "myGrid2PubKey";
		
		PeerControlClient peerControlClient2 = EasyMock.createMock(PeerControlClient.class);
		
		DeploymentID pccID2 = new DeploymentID(new ContainerID("pcc2", "broker2", "broker"), myGrid2PubKey);
		AcceptanceTestUtil.publishTestObject(peerComponent, pccID2, peerControlClient2, PeerControlClient.class);
		
		AcceptanceTestUtil.setExecutionContext(peerComponent, pcOD, pccID2);
		
		try {
			peerControl.addUser(peerControlClient2, user2.getUsername() + "@" + user2.getServerAddress(), user2.getUserpassword());
		} catch (CommuneRuntimeException e) {
			//do nothing - the user is already added.
		}
		
		DeploymentID lwpc2OID = req_108_Util.login(peerComponent, user2, myGrid2PubKey);
		
		LocalWorkerProviderClient lwpc2 = (LocalWorkerProviderClient) AcceptanceTestUtil.getBoundObject(lwpc2OID);
		
		//Request six workers for local1
		JobSpec jobSpec = createJobSpec("label");
		RequestSpec requestSpec1 = new RequestSpec(0, jobSpec, 1, "mem < 8", 6, 0, 0);
		
		WorkerAllocation allocationA = new WorkerAllocation(workerAID);
		req_011_Util.requestForLocalConsumer(peerComponent, new TestStub(lwpc1OID, lwpc1), requestSpec1, allocationA);
		
		//GIS client receive a remote worker provider (sub11)
		String sub11PublicKey = "publicKey11";
		WorkerSpec remoteWorkerSpec11 = workerAcceptanceUtil.createWorkerSpec("U1", "SS11");
		remoteWorkerSpec11.putAttribute(WorkerSpec.ATT_MEM, "4");
		TestStub sub11Stub = req_020_Util.receiveRemoteWorkerProvider(peerComponent, requestSpec1, "rwp11User", 
				"rwp11Server", sub11PublicKey, remoteWorkerSpec11);
		
		RemoteWorkerProvider sub11 = (RemoteWorkerProvider) sub11Stub.getObject();
		
		DeploymentID sub11ID = sub11Stub.getDeploymentID();
		
		//Remote worker provider client receive a remote worker (RW11)
		String worker11PubKey = "worker11PubKey"; 
		DeploymentID rwm11OID = req_018_Util.receiveRemoteWorker(peerComponent, sub11, sub11ID, remoteWorkerSpec11, worker11PubKey, myGrid1PubKey).getDeploymentID();
		
		//GIS client receive a remote worker provider (sub2)
		String sub2PublicKey = "publicKey2";
		WorkerSpec remoteWorkerSpec20 = workerAcceptanceUtil.createWorkerSpec("U1", "SS2");
		remoteWorkerSpec20.putAttribute(WorkerSpec.ATT_MEM, "4");

		TestStub sub2Stub = req_020_Util.receiveRemoteWorkerProvider(peerComponent, requestSpec1, "rwp22User", 
				"rwp22Server", sub2PublicKey, remoteWorkerSpec20);
		
		RemoteWorkerProvider sub2 = (RemoteWorkerProvider) sub2Stub.getObject();
		
		DeploymentID sub2ID = sub2Stub.getDeploymentID();
		
		//Remote worker provider client receive a remote worker (RW20)
		String worker20PubKey = "worker20PubKey"; 
		DeploymentID rwm20OID = req_018_Util.receiveRemoteWorker(peerComponent, sub2, sub2ID, remoteWorkerSpec20, worker20PubKey, myGrid1PubKey).getDeploymentID();
		
		//GIS client receive a remote worker provider (r1)
		String r1PublicKey = "r1PublicKey";
		WorkerSpec remoteWorkerSpec1 = workerAcceptanceUtil.createWorkerSpec("U1", "S1");
		remoteWorkerSpec1.putAttribute(WorkerSpec.ATT_MEM, "4");
		TestStub r1Stub = req_020_Util.receiveRemoteWorkerProvider(peerComponent, requestSpec1, "rwp1User", 
				"rwp1Server", r1PublicKey, remoteWorkerSpec1);
		
		RemoteWorkerProvider r1 = (RemoteWorkerProvider) r1Stub.getObject();
		
		DeploymentID r1ID = r1Stub.getDeploymentID();
		
		//Remote worker provider client receive a remote worker (rw1)
		String worker1PubKey = "worker1PubKey"; 
		DeploymentID rwm1OID = req_018_Util.receiveRemoteWorker(peerComponent, r1, r1ID, remoteWorkerSpec1, worker1PubKey, myGrid1PubKey).getDeploymentID();
		
		//GIS client receive a remote worker provider (r2)
		String r2PublicKey = "r2PublicKey";
		WorkerSpec remoteWorkerSpec2 = workerAcceptanceUtil.createWorkerSpec("U1", "S2");
		remoteWorkerSpec2.putAttribute(WorkerSpec.ATT_MEM, "4");
		TestStub r2Stub = req_020_Util.receiveRemoteWorkerProvider(peerComponent, requestSpec1, "rwp2User", 
				"rwp2Server", r2PublicKey, remoteWorkerSpec2);
		
		RemoteWorkerProvider r2 = (RemoteWorkerProvider) r2Stub.getObject();
		
		DeploymentID r2ID = r2Stub.getDeploymentID();
		
		//Remote worker provider client receive a remote worker (rw2)
		String worker2PubKey = "worker2PubKey"; 
		DeploymentID rwm2OID = req_018_Util.receiveRemoteWorker(peerComponent, r2, r2ID, remoteWorkerSpec2, worker2PubKey, myGrid1PubKey).getDeploymentID();
		
		//Change worker status to ALLOCATED FOR MYGRID (workerA)
		req_025_Util.changeWorkerStatusToAllocatedForBroker(peerComponent, lwpc1OID, workerAID, workerSpecA, requestSpec1);
		
		//Change worker status to ALLOCATED FOR MYGRID (RW11)
		ObjectDeployment lwpc1OD = new ObjectDeployment(peerComponent.getContainer(), lwpc1OID, AcceptanceTestUtil.getBoundObject(lwpc1OID));
		
		ObjectDeployment rwmcOD = peerAcceptanceUtil.getRemoteWorkerManagementClientDeployment();
		
		req_025_Util.changeWorkerStatusToAllocatedForBroker(peerComponent, lwpc1OD, rwmcOD, 
				rwm11OID, remoteWorkerSpec11, requestSpec1);
		
		//Change worker status to ALLOCATED FOR MYGRID (RW20)
		req_025_Util.changeWorkerStatusToAllocatedForBroker(peerComponent, lwpc1OD, rwmcOD, 
				rwm20OID, remoteWorkerSpec20, requestSpec1);
		
		//Change worker status to ALLOCATED FOR MYGRID (RW1)
		req_025_Util.changeWorkerStatusToAllocatedForBroker(peerComponent, lwpc1OD, rwmcOD, 
				rwm1OID, remoteWorkerSpec1, requestSpec1);
		
		//Change worker status to ALLOCATED FOR MYGRID (RW2)
		req_025_Util.changeWorkerStatusToAllocatedForBroker(peerComponent, lwpc1OD, rwmcOD, 
				rwm2OID, remoteWorkerSpec2, requestSpec1);
		
		//Report a received favour (workerA)
		req_027_Util.reportReplicaAccounting(peerComponent, lwpc1OID, 
				new GridProcessAccounting(requestSpec1, workerAID.toString(), workerAID.getPublicKey(), 
						100., 0., GridProcessState.FINISHED, workerSpecA), true);
		
		//Report a received favour (RW11)
		req_027_Util.reportReplicaAccounting(peerComponent, lwpc1OID, 
				new GridProcessAccounting(requestSpec1, rwm11OID.toString(), rwm11OID.getPublicKey(), 
						80., 0., GridProcessState.FINISHED, remoteWorkerSpec11), false);
		
		//Report a received favour (RW20)
		req_027_Util.reportReplicaAccounting(peerComponent, lwpc1OID, 
				new GridProcessAccounting(requestSpec1, rwm20OID.toString(), rwm20OID.getPublicKey(), 
						150., 0., GridProcessState.FINISHED, remoteWorkerSpec20), false);
		
		//Report a received favour (RW1)
		req_027_Util.reportReplicaAccounting(peerComponent, lwpc1OID, 
				new GridProcessAccounting(requestSpec1, rwm1OID.toString(), rwm1OID.getPublicKey(), 
						120., 0., GridProcessState.FINISHED, remoteWorkerSpec1), false);
		
		//Report a received favour (RW2)
		req_027_Util.reportReplicaAccounting(peerComponent, lwpc1OID, 
				new GridProcessAccounting(requestSpec1, rwm2OID.toString(), rwm2OID.getPublicKey(), 
						120., 0., GridProcessState.FINISHED, remoteWorkerSpec2), false);
		
		//Finish the request
		WorkerAllocation remoteAllocation11 = new WorkerAllocation(rwm11OID);
		WorkerAllocation remoteAllocation20 = new WorkerAllocation(rwm20OID);
		WorkerAllocation remoteAllocation1 = new WorkerAllocation(rwm1OID);
		WorkerAllocation remoteAllocation2 = new WorkerAllocation(rwm2OID);
		
		RemoteAllocation remotePeer11 = new RemoteAllocation(sub11, AcceptanceTestUtil.createList(remoteAllocation11));
		RemoteAllocation remotePeer20 = new RemoteAllocation(sub2, AcceptanceTestUtil.createList(remoteAllocation20));
		RemoteAllocation remotePeer1 = new RemoteAllocation(r1, AcceptanceTestUtil.createList(remoteAllocation1));
		RemoteAllocation remotePeer2 = new RemoteAllocation(r2, AcceptanceTestUtil.createList(remoteAllocation2));

		ObjectDeployment lwpOD = peerAcceptanceUtil.getLocalWorkerProviderDeployment();
		
		req_014_Util.finishRequestWithLocalAndRemoteWorkers(peerComponent, peerAcceptanceUtil.getLocalWorkerProviderProxy(), lwpOD, 
				myGrid1PubKey, null, requestSpec1, AcceptanceTestUtil.createList(allocationA), 
				new TestStub(sub11ID, remotePeer11), new TestStub(sub2ID, remotePeer20), new TestStub(r1ID, remotePeer1), 
				new TestStub(r2ID, remotePeer2));
		
		//Request five workers for local2
		RequestSpec requestSpec2 = new RequestSpec(0, jobSpec, 2, "mem < 8", 5, 0, 0);
		
//		peerAcceptanceUtil.getDiscoveryServiceClient().workerProviderIsUp(sub11, sub11ID, AcceptanceTestUtil.getCertificateMock(sub11ID));
//		peerAcceptanceUtil.getDiscoveryServiceClient().workerProviderIsUp(sub2, sub2ID, AcceptanceTestUtil.getCertificateMock(sub2ID));
//		peerAcceptanceUtil.getDiscoveryServiceClient().workerProviderIsUp(r1, r1ID, AcceptanceTestUtil.getCertificateMock(r1ID));
//		peerAcceptanceUtil.getDiscoveryServiceClient().workerProviderIsUp(r2, r2ID, AcceptanceTestUtil.getCertificateMock(r2ID));
		
		List<TestStub> rwps = new ArrayList<TestStub>();
		rwps.add(new TestStub(sub11ID, sub11));
		rwps.add(new TestStub(sub2ID, sub2));
		rwps.add(new TestStub(r1ID, r1));
		rwps.add(new TestStub(r2ID, r2));
		
		req_011_Util.requestForLocalConsumer(peerComponent, new TestStub(lwpc2OID, lwpc2), requestSpec2, rwps, 
				allocationA);
		
		//GIS client receive a remote worker provider (sub10)
		String sub10PublicKey = "publicKey10";
		WorkerSpec remoteWorkerSpec10 = workerAcceptanceUtil.createWorkerSpec("U1", "SS10");
		remoteWorkerSpec10.putAttribute(WorkerSpec.ATT_MEM, "4");
		TestStub sub10Stub = req_020_Util.receiveRemoteWorkerProvider(peerComponent, requestSpec2, 
				"rwp10User", "rwp10Server", sub10PublicKey, remoteWorkerSpec10);
		
		RemoteWorkerProvider sub10 = (RemoteWorkerProvider) sub10Stub.getObject();
		
		DeploymentID sub10ID = sub10Stub.getDeploymentID();
		
		//Remote worker provider client receive a remote worker (RW10)
		String worker10PubKey = "worker10PubKey"; 
		DeploymentID rwm10OID = req_018_Util.receiveRemoteWorker(peerComponent, sub10, sub10ID, remoteWorkerSpec10, worker10PubKey, myGrid2PubKey).getDeploymentID();
		
		//GIS client receive a remote worker provider (r2)
		WorkerSpec remoteWorkerSpec4 = workerAcceptanceUtil.createWorkerSpec("U2", "S2");
		remoteWorkerSpec4.putAttribute(WorkerSpec.ATT_MEM, "4");
//		r2Stub = req_020_Util.receiveRemoteWorkerProvider(peerComponent, requestSpec2, "rwp2User", 
//				"rwp2Server", r2PublicKey, remoteWorkerSpec2, remoteWorkerSpec4);
//		
//		r2 = (RemoteWorkerProvider) r2Stub.getObject();
//		
//		rwm2OID = r2Stub.getDeploymentID();
		
		//Remote worker provider client receive a remote worker (RW2)
		rwm2OID = req_018_Util.receiveRemoteWorker(peerComponent, r2, r2ID, remoteWorkerSpec2, worker2PubKey, myGrid2PubKey).getDeploymentID();
		
		//Remote worker provider client receive a remote worker (RW4)
		String worker4PubKey = "worker4PubKey"; 
		DeploymentID rwm4OID = req_018_Util.receiveRemoteWorker(peerComponent, r2, r2ID, remoteWorkerSpec4, worker4PubKey, myGrid2PubKey).getDeploymentID();
		
		//Change worker status to ALLOCATED FOR MYGRID (workerA)
		req_025_Util.changeWorkerStatusToAllocatedForBroker(peerComponent, lwpc2OID, workerAID, workerSpecA, requestSpec2);
		
		//Change worker status to ALLOCATED FOR MYGRID (RW10)
		ObjectDeployment lwpc2OD = new ObjectDeployment(peerComponent.getContainer(), lwpc2OID, AcceptanceTestUtil.getBoundObject(lwpc2OID));
		
		req_025_Util.changeWorkerStatusToAllocatedForBroker(peerComponent, lwpc2OD, rwmcOD, 
				rwm10OID, remoteWorkerSpec10, requestSpec2);
		
		//Change worker status to ALLOCATED FOR MYGRID (RW2)
		req_025_Util.changeWorkerStatusToAllocatedForBroker(peerComponent, lwpc2OD, rwmcOD, 
				rwm2OID, remoteWorkerSpec2, requestSpec2);
		
		//Change worker status to ALLOCATED FOR MYGRID (RW4)
		req_025_Util.changeWorkerStatusToAllocatedForBroker(peerComponent, lwpc2OD, rwmcOD, 
				rwm4OID, remoteWorkerSpec4, requestSpec2);
		
		//Report a received favour (workerA)
		req_027_Util.reportReplicaAccounting(peerComponent, lwpc2OID, 
				new GridProcessAccounting(requestSpec2, workerAID.toString(), workerAID.getPublicKey(), 
						100., 0., GridProcessState.FINISHED, workerSpecA), true);
		
		//Report a received favour (RW10)
		req_027_Util.reportReplicaAccounting(peerComponent, lwpc2OID, 
				new GridProcessAccounting(requestSpec2, rwm10OID.toString(), rwm10OID.getPublicKey(), 
						300., 0., GridProcessState.FINISHED, remoteWorkerSpec10), false);
		
		//Report a received favour (RW4)
		req_027_Util.reportReplicaAccounting(peerComponent, lwpc2OID, 
				new GridProcessAccounting(requestSpec2, rwm4OID.toString(), rwm4OID.getPublicKey(), 
						130., 0., GridProcessState.FINISHED, remoteWorkerSpec4), false);
		
		//Report a received favour (RW2)
		req_027_Util.reportReplicaAccounting(peerComponent, lwpc2OID, 
				new GridProcessAccounting(requestSpec2, rwm2OID.toString(), rwm2OID.getPublicKey(), 
						40., 0., GridProcessState.FINISHED, remoteWorkerSpec2), false);
		
		
		//Finish the request
		WorkerAllocation remoteAllocation10 = new WorkerAllocation(rwm10OID);
		remoteAllocation2 = new WorkerAllocation(rwm2OID);
		WorkerAllocation remoteAllocation4 = new WorkerAllocation(rwm4OID);
		
		RemoteAllocation remotePeer10 = new RemoteAllocation(sub10, AcceptanceTestUtil.createList(remoteAllocation10));
		remotePeer2 = new RemoteAllocation(r2, AcceptanceTestUtil.createList(remoteAllocation2, remoteAllocation4));

		req_014_Util.finishRequestWithLocalAndRemoteWorkers(peerComponent, peerAcceptanceUtil.getLocalWorkerProviderProxy(), lwpOD,  
				myGrid2PubKey, null, requestSpec2, AcceptanceTestUtil.createList(allocationA), 
				new TestStub(sub10ID, remotePeer10), new TestStub(r2ID, remotePeer2));
		
		//Stop the Peer
		req_010_Util.notNiceStopPeer(peerComponent);
		//BindRegistry.reset();
		PeerAcceptanceUtil.copyTrustFile(AUX_FILES_PATH+"trust.xml");
		
		//Start the peer with the property peer.rankingfile set to the file that was previously used
		peerComponent = peerAcceptanceUtil.createPeerComponent(getComponentContext());
		
		//Expect the peer to schedule the file save of the network of favors data
		req_115_Util.startPeerVerifyingAccountingSavingWithNoError(peerComponent);
		
		//Set workers
		req_010_Util.setWorkers(peerComponent, AUX_FILES_PATH + "TI_0033.sdf", getComponentContext());
		
		//Notify workers recovery
		workerAID = req_019_Util.notifyWorkerRecovery(peerComponent, workerSpecA, workerAPublicKey);
		workerBID = req_019_Util.notifyWorkerRecovery(peerComponent, workerSpecB, workerBPublicKey);
		workerCID = req_019_Util.notifyWorkerRecovery(peerComponent, workerSpecC, workerCPublicKey);
		workerDID = req_019_Util.notifyWorkerRecovery(peerComponent, workerSpecD, workerDPublicKey);
		workerEID = req_019_Util.notifyWorkerRecovery(peerComponent, workerSpecE, workerEPublicKey);
		workerFID = req_019_Util.notifyWorkerRecovery(peerComponent, workerSpecF, workerFPublicKey);
		workerGID = req_019_Util.notifyWorkerRecovery(peerComponent, workerSpecG, workerGPublicKey);
		workerHID = req_019_Util.notifyWorkerRecovery(peerComponent, workerSpecH, workerHPublicKey);
		workerIID = req_019_Util.notifyWorkerRecovery(peerComponent, workerSpecI, workerIPublicKey);
		workerJID = req_019_Util.notifyWorkerRecovery(peerComponent, workerSpecJ, workerJPublicKey);
		workerKID = req_019_Util.notifyWorkerRecovery(peerComponent, workerSpecK, workerKPublicKey);
		workerLID = req_019_Util.notifyWorkerRecovery(peerComponent, workerSpecL, workerLPublicKey);
		
		//Change workers status to IDLE
		req_025_Util.changeWorkerStatusToIdle(peerComponent, workerLID);
		req_025_Util.changeWorkerStatusToIdle(peerComponent, workerKID);
		req_025_Util.changeWorkerStatusToIdle(peerComponent, workerJID);
		req_025_Util.changeWorkerStatusToIdle(peerComponent, workerIID);
		req_025_Util.changeWorkerStatusToIdle(peerComponent, workerHID);
		req_025_Util.changeWorkerStatusToIdle(peerComponent, workerGID);
		req_025_Util.changeWorkerStatusToIdle(peerComponent, workerFID);
		req_025_Util.changeWorkerStatusToIdle(peerComponent, workerEID);
		req_025_Util.changeWorkerStatusToIdle(peerComponent, workerDID);
		req_025_Util.changeWorkerStatusToIdle(peerComponent, workerCID);
		req_025_Util.changeWorkerStatusToIdle(peerComponent, workerBID);
		req_025_Util.changeWorkerStatusToIdle(peerComponent, workerAID);
		
		//NodeWiz recovery
		req_020_Util.notifyDiscoveryServiceRecovery(peerComponent, dsID);
		
		//Login with two valid users
		lwpc1OID = req_108_Util.login(peerComponent, user1, myGrid1PubKey);
		lwpc2OID = req_108_Util.login(peerComponent, user2, myGrid2PubKey);
		
		
		//Request five workers for R3
		RequestSpec requestSpec3 = new RequestSpec(0, jobSpec, 3, "", 5, 0, 0);
		DeploymentID r3ID = new DeploymentID(new ContainerID("rwpc3User", "rwpc3Server", PeerConstants.MODULE_NAME, "r3PubKey"),
				PeerConstants.REMOTE_ACCESS_OBJECT_NAME);
		
		allocationA = new WorkerAllocation(workerAID);	
		WorkerAllocation allocationB = new WorkerAllocation(workerBID);
		WorkerAllocation allocationC = new WorkerAllocation(workerCID);
		WorkerAllocation allocationD = new WorkerAllocation(workerDID);
		WorkerAllocation allocationE = new WorkerAllocation(workerEID);
		
		req_011_Util.requestForRemoteClient(peerComponent, r3ID, requestSpec3, 3, 
				allocationA, allocationB, allocationC, allocationD, allocationE);
				
		//Request ten workers for R1
		RequestSpec requestSpec4 = new RequestSpec(0, jobSpec, 4, "", 10, 0, 0);
//		r1ID = new DeploymentID(new ContainerID("rwpc3User", "rwpc3Server", PeerConstants.MODULE_NAME, "r1PublicKey"),
//				PeerConstants.REMOTE_ACCESS_OBJECT_NAME);
		
		WorkerAllocation allocationF = new WorkerAllocation(workerFID);
		WorkerAllocation allocationG = new WorkerAllocation(workerGID);
		WorkerAllocation allocationH = new WorkerAllocation(workerHID);
		WorkerAllocation allocationI = new WorkerAllocation(workerIID);
		WorkerAllocation allocationJ = new WorkerAllocation(workerJID);
		WorkerAllocation allocationK = new WorkerAllocation(workerKID);
		WorkerAllocation allocationL = new WorkerAllocation(workerLID);
		allocationE.addLoserConsumer(r3ID);
		allocationD.addLoserConsumer(r3ID);
		allocationC.addLoserConsumer(r3ID);
		
		req_011_Util.requestForRemoteClient(peerComponent, r1ID, requestSpec4, Req_011_Util.DO_NOT_LOAD_SUBCOMMUNITIES, 
				allocationF, allocationG, allocationH, allocationI, allocationJ, 
				allocationK, allocationL, allocationE, allocationD, allocationC);
		
		
		//Request ten workers for R2
//		r2ID = new DeploymentID(new ContainerID("rwpc2User", "rwpc2server", PeerConstants.MODULE_NAME),
//				PeerConstants.REMOTE_ACCESS_OBJECT_NAME);
		
		RequestSpec requestSpec5 = new RequestSpec(0, jobSpec, 5, "(mem < 4096) AND (mem > 4)", 10, 0, 0);
		
		allocationB.addLoserConsumer(r3ID);
		allocationC.addLoserConsumer(r1ID);
		allocationD.addLoserConsumer(r1ID);
		allocationE.addLoserConsumer(r1ID);
		allocationJ.addLoserConsumer(r1ID);
		allocationI.addLoserConsumer(r1ID);
		allocationH.addLoserConsumer(r1ID);
		allocationG.addLoserConsumer(r1ID);
		allocationF.addLoserConsumer(r1ID);
		
		req_011_Util.requestForRemoteClient(peerComponent, r2ID, requestSpec5, Req_011_Util.DO_NOT_LOAD_SUBCOMMUNITIES, 
				allocationB, allocationC, allocationD, allocationE, 
				allocationJ, allocationI, allocationH, allocationG, allocationF);
		
		//Request four workers for Sub10
//		DeploymentID rsub10ID = new DeploymentID(new ContainerID("rwpc10User", "rwpc10server", 
//				PeerConstants.MODULE_NAME, "rsub10PubKey"), PeerConstants.REMOTE_ACCESS_OBJECT_NAME);
		
		RequestSpec requestSpec6 = new RequestSpec(0, jobSpec, 6, "mem > 64", 4, 0, 0);
		
		allocationF.addLoserConsumer(r2ID);
		allocationG.addLoserConsumer(r2ID);
		allocationH.addLoserConsumer(r2ID);
		allocationL.addLoserConsumer(r1ID);
		
		req_011_Util.requestForRemoteClient(peerComponent, sub10ID, requestSpec6, Req_011_Util.DO_NOT_LOAD_SUBCOMMUNITIES, 
				allocationL, allocationF, allocationG, allocationH);
		
		//Request four workers for Sub2
//		DeploymentID rsub2ID = new DeploymentID(new ContainerID("rwpc20User", "rwpc20server", 
//				PeerConstants.MODULE_NAME, "rsub2PublicKey"), PeerConstants.REMOTE_ACCESS_OBJECT_NAME);
		
		RequestSpec requestSpec7 = new RequestSpec(0, jobSpec, 7, "mem > 256", 4, 0, 0);
		
		allocationI.addLoserConsumer(r2ID);
		allocationJ.addLoserConsumer(r2ID);
		allocationK.addLoserConsumer(r1ID);
		
		req_011_Util.requestForRemoteClient(peerComponent, sub2ID, requestSpec7, Req_011_Util.DO_NOT_LOAD_SUBCOMMUNITIES, 
				allocationK, allocationI, allocationJ);
		
		//Request four workers for Sub12
		DeploymentID rsub12ID = new DeploymentID(new ContainerID("rwpc12User", "rwpc12server", 
				PeerConstants.MODULE_NAME, "publicKey12"), PeerConstants.REMOTE_ACCESS_OBJECT_NAME);
		
		RequestSpec requestSpec8 = new RequestSpec(0, jobSpec, 8, "mem > 32", 4, 0, 0);
		
		allocationE.addLoserConsumer(r2ID);
		allocationK.addLoserConsumer(sub2ID);
		allocationI.addLoserConsumer(sub2ID);
		allocationJ.addLoserConsumer(sub2ID);
		
		req_011_Util.requestForRemoteClient(peerComponent, rsub12ID, requestSpec8, Req_011_Util.DO_NOT_LOAD_SUBCOMMUNITIES, 
				allocationE, allocationI, allocationJ, allocationK);
		
		//Request five workers for Sub11
//		DeploymentID rsub11ID = new DeploymentID(new ContainerID("rwpc11User", "rwpc11server", PeerConstants.MODULE_NAME),
//				PeerConstants.REMOTE_ACCESS_OBJECT_NAME);
		
		RequestSpec requestSpec9 = new RequestSpec(0, jobSpec, 9, "mem > 8", 5, 0, 0);
		
		allocationD.addLoserConsumer(r2ID);
		allocationC.addLoserConsumer(r2ID);
		allocationI.addLoserConsumer(rsub12ID);
		allocationJ.addLoserConsumer(rsub12ID);
		allocationK.addLoserConsumer(rsub12ID);
		
		req_011_Util.requestForRemoteClient(peerComponent, sub11ID, requestSpec9, Req_011_Util.DO_NOT_LOAD_SUBCOMMUNITIES, 
				allocationD, allocationC, allocationK, allocationI, allocationJ);

		//Request seven workers for local1
		RequestSpec requestSpec10 = new RequestSpec(0, jobSpec, 10, "", 7, 0, 0);
		
		allocationA.addLoserConsumer(r3ID);
		allocationB.addLoserConsumer(r2ID);
		allocationE.addLoserConsumer(rsub12ID);
		allocationK.addLoserConsumer(sub11ID);
		allocationJ.addLoserConsumer(sub11ID);
		allocationL.addLoserConsumer(sub10ID);
		allocationI.addLoserConsumer(sub11ID);
		
		req_011_Util.requestForLocalConsumer(peerComponent, new TestStub(lwpc1OID, lwpc1), requestSpec10, 
				allocationA, allocationB, allocationE, allocationK,
				allocationJ, allocationL, allocationI);
		
		//The consumer local1 set the worker A as unwanted
		allocationA = new WorkerAllocation(workerAID);
		
		ScheduledFuture<?> future10 = req_016_Util.unwantedMockWorker(peerComponent, allocationA, requestSpec10, 
				lwpc1OID, true, null);
		
		//Request eight workers for local2
		RequestSpec requestSpec11 = new RequestSpec(0, jobSpec, 11, "", 8, 0, 0);
		allocationH.addLoserConsumer(sub10ID);
		allocationC.addLoserConsumer(sub11ID);
		allocationG.addLoserConsumer(sub10ID);
		allocationD.addLoserConsumer(sub11ID);
		allocationF.addLoserConsumer(sub10ID);
		
		req_011_Util.requestForLocalConsumer(peerComponent, new TestStub(lwpc2OID, lwpc2), requestSpec11, 
				allocationA, allocationH, allocationC, 
				allocationG, allocationD, allocationF);
		
		//The consumer local2 set the worker A as unwanted
		req_016_Util.unwantedMockWorker(peerComponent, allocationA, requestSpec11, lwpc2OID, false, null);
		
		//The consumer local2 set the worker c as unwanted
		allocationC.addWinnerConsumer(lwpc1OID);
		req_016_Util.unwantedMockWorker(peerComponent, allocationC, requestSpec11, lwpc2OID, false, future10);

	}
}